package server2;

import java.net.InetSocketAddress;
import java.util.Hashtable;
import java.util.Observable;

import org.apache.log4j.Logger;
import org.apache.mina.core.session.IoSession;

import exception.NoIpException;
import util.DataTypeTranslater;

/**
 * 缃戠粶閫昏緫灞�
 * 
 * @author Feng
 * 
 */
public class ServerModel extends Observable {
	private ServerModel serverModel;
	Logger logger = Logger.getLogger(this.getClass());

	// 蹇冭烦鍖呴棿闅�(5绉�)
	public static final int KEEP_ALIVE_PACKET_TIME = 5000;
	// 杞"绛夊緟client鍥炲"鍒楄〃锛坵aitClientRepTable锛夌殑闂撮殧
	public static final int CHECK_WAIT_CLIENT_RESPONSE_DELTA_TIME = 1000;

	// public static ServerModel instance = new ServerModel();
	// Client璇锋眰闃熷垪
	// private LinkedBlockingQueue<NetworkMessage> requestQueue = new
	// LinkedBlockingQueue<NetworkMessage>();
	// 宸茶繛鎺ョ敤鎴蜂俊鎭〃(Key 涓篒oSession.getRemoteAddress().toString)
	private Hashtable<String, ClientUser> clientUserIpTable = new Hashtable<String, ClientUser>();
	private Hashtable<String, ClientUser> clientUserIdTable = new Hashtable<String, ClientUser>();

	// 鐩戝惉瀹㈡埛绔洖澶嶇殑琛�
	// private Hashtable<String, WaitClientResponse> waitClientRepTable = new
	// Hashtable<String, WaitClientResponse>();

	public ServerModel() {
//		init();
	}

	public ServerModel getServerModel() {
		return serverModel;
	}

	public void setServerModel(ServerModel serverModel) {
		this.serverModel = serverModel;
	}

	/**
	 * 鍒涘缓涓�涓殢鏈虹殑MessageId
	 * 
	 * @author Feng
	 * @return
	 */
	public static byte[] createMessageId() {
		return DataTypeTranslater.floatToBytes((float) Math.random());
	}

	/**
	 * 鍒濆鍖�
	 * 
	 * @author Feng
	 */
	public void init() {
		
	}

	/**
	 * 寰�瀹㈡埛绔姹傚垪琛ㄤ腑鍔犲叆涓�鏉¤姹�
	 * 
	 * @param ioSession
	 * @param arrayBytes
	 * @author Feng
	 * @throws InterruptedException
	 */
	// public void addClientRequestToQueue(IoSession ioSession, byte[]
	// byteArray) throws InterruptedException {
	// requestQueue.put(new NetworkMessage(ioSession, byteArray));
	// }

	/**
	 * 寰�鈥滃凡杩炴帴鐢ㄦ埛淇℃伅琛ㄢ�濅腑娣诲姞涓�涓柊鐢ㄦ埛
	 * 
	 * @param key
	 * @param clientUser
	 * @author Feng
	 * @throws NoIpException
	 */
	public void addClientUserToTable(IoSession ioSession, ClientUser clientUser) throws NoIpException {
		synchronized (clientUserIpTable) {
			clientUser.onLine = true;
			clientUserIpTable.put(getIoSessionKey(ioSession), clientUser);
		}
	}

	/**
	 * 璁剧疆鐢ㄦ埛鐧婚檰
	 * 
	 * @param clientUser
	 * @param userId
	 * @author Feng
	 */
	public void clientUserLogin(ClientUser clientUser, String userId) {
		clientUser.onLine = true;
		clientUser.userId = userId;
		clientUserIdTable.put(userId, clientUser);
	}

	/**
	 * 璁剧疆鐢ㄦ埛鐧婚檰
	 * 
	 * @param clientUser
	 * @param userId
	 * @author Feng
	 */
	public void clientUserLogout(ClientUser clientUser) {
		try {
			System.out.println(clientUserIdTable.containsKey(clientUser.userId));
			clientUser.onLine = false;
			clientUserIdTable.remove(clientUser.userId);
//			clientUser.userId = null;
		} catch (Exception e) {
			e.printStackTrace();
			logger.error("Logout Error!");
		}
	}

	/**
	 * 浠巌osession鐢熸垚Key
	 * 
	 * @param ioSession
	 * @return
	 * @throws NoIpException
	 */
	public static String getIoSessionKey(IoSession ioSession) throws NoIpException  {
		// System.err.println("1.2  " + (ioSession.getRemoteAddress() == null));
		if (ioSession.getRemoteAddress() == null)
			throw new NoIpException();
		
		return ((InetSocketAddress) ioSession.getRemoteAddress()).getAddress().toString() + ":"
				+ ((InetSocketAddress) ioSession.getRemoteAddress()).getPort();
	}

	/**
	 * 浠庘�滃凡杩炴帴鐢ㄦ埛淇℃伅琛ㄢ�濅腑鑾峰彇鐢ㄦ埛
	 * 
	 * @param key
	 * @return ClientUser
	 * @author Feng
	 */
	public ClientUser getClientUserFromTable(String key) {
		synchronized (clientUserIpTable) {
			return clientUserIpTable.get(key);
		}
	}

	public ClientUser getClientUserFromTable(IoSession ioSession) throws NoIpException {
		synchronized (clientUserIpTable) {
			return getClientUserFromTable(getIoSessionKey(ioSession));
		}
	}

	/**
	 * 鏍规嵁userId浠庘�滃凡杩炴帴鐢ㄦ埛淇℃伅琛ㄢ�濅腑鑾峰彇鐢ㄦ埛
	 * 
	 * @param userId
	 * @return
	 */
	public ClientUser getClientUserByUserId(String userId) {
		ClientUser user = clientUserIdTable.get(userId);
		try {
			if (user == null || user.userId == null || user.userId.equals("") || user.onLine == false || !user.ioSession.isConnected())
				clientUserIdTable.remove(userId);
		} catch (Exception e) {
			return null;
		}

		return user;
		// Iterator iterator = clientUserIpTable.keySet().iterator();
		// String key;
		// ClientUser user;
		//
		// synchronized (clientUserIpTable) {
		// while (iterator.hasNext()) {
		//
		// key = iterator.next().toString();
		//
		// if (!clientUserIpTable.containsKey(key))
		// continue;
		//
		// user = clientUserIpTable.get(key);
		//
		// if (user.userId == null)
		// continue;
		//
		// if (user.userId.equals(userId))
		// return user;
		// }
		// }
		// return null;
	}

	/**
	 * 浠庡湪绾跨敤鎴蜂俊鎭〃鍒犻櫎涓�涓敤鎴�
	 * 
	 * @param key
	 */
	public void removeClientUserFromTable(String key) {
		synchronized (clientUserIpTable) {
			clientUserIpTable.remove(key);
		}
	}

	/**
	 * 娣诲姞涓�涓瓑寰呭鎴风鍥炲鐨勭洃鍚紙鏈嶅姟鍣ㄥ悜瀹㈡埛绔彂閫佹秷鎭悗锛岃姹傚鎴风鍥炲锛�
	 * 
	 * @param ioSession
	 * @param key
	 * @param messageHasSentww
	 * @author Feng
	 */
	// public void addClientResponseListener(IoSession ioSession, byte[] key,
	// byte[] messageHasSent,
	// WaitClientResponseCallBack waitClientResponseCallBack) {
	// WaitClientResponse waitClientResponse = new WaitClientResponse(ioSession,
	// messageHasSent, waitClientResponseCallBack);
	// waitClientResponse.time = new Date().getTime();
	// // 鍔犲叆鍒扳�滅瓑寰呭洖澶嶈〃鈥濅腑锛岀敱CheckWaitClientResponseThread 绾跨▼杩涜杞
	// System.err.println("add Listener, key: " + key.toString());
	// waitClientRepTable.put(key.toString(), waitClientResponse);
	// }

	/**
	 * 鍒犻櫎涓�涓瓑寰呭鎴风鍥炲鐨勭洃鍚紙鏈嶅姟鍣ㄥ悜瀹㈡埛绔彂閫佹秷鎭悗锛岃姹傚鎴风鍥炲锛�
	 * 
	 * @param ioSession
	 * @param key
	 * @param messageHasSent
	 * @author Feng
	 */
	// public void removeClientResponseListener(byte[] key) {
	// synchronized (waitClientRepTable) {
	// waitClientRepTable.remove(key);
	// }
	// }

	/**
	 * 鏌ユ壘涓�涓瓑寰呭鎴风鍥炲鐨勭洃鍚紙鏈嶅姟鍣ㄥ悜瀹㈡埛绔彂閫佹秷鎭悗锛岃姹傚鎴风鍥炲锛�
	 * 
	 * @param ioSession
	 * @param key
	 * @param messageHasSent
	 * @author Feng
	 */
	// public WaitClientResponse getClientResponseListener(byte[] key) {
	// synchronized (waitClientRepTable) {
	// return waitClientRepTable.get(key);
	// }
	// }

	/**
	 * 骞挎挱鍓嶇殑璁剧疆鍙樻洿
	 */
	public void setChange() {
		super.setChanged();
	}

	public void notify(Object obj) {
		setChange();
		notifyObservers(this);
	}
}
